/**
 * Copyright (C) 2009+ Spark Zheng
 *
 * @file        test/test_udp_server.c 
 * @date        2010-04-24
 * @brief	test_module
 *		testsuit for libdserver, run a tcp/udp server with libevent
 *		-TCP protocol
 *		-UDP protocol
 * @see         dserver
 * @history
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include <dlib/log.h>
#include <dlib/str.h>

#include "libdserver.h"

static int session_init(void *arg);
static prot_ret_t session_worker(void *arg);
static void session_exit(void *arg);

int main(int argc, char **argv)
{
	if (argc < 3) {
		fprintf(stderr, "USAGE: test_udp_server ip port\n");
		return -1;
	}

	int ret = 0;
	dserver_handler_t *handler = NULL;
	const char *ip = argv[1];
	in_port_t port = (in_port_t)atoi(argv[2]);

	fprintf(stderr, "build up udp server with ip:%s, port:%u.\n", ip, port);

	if (dserver_log_init("./log") < 0) {
		fprintf(stderr, "udpserver_log init error.\n");
		ret = -10;
		goto end;
	}

	handler = dserver_udpserver_init(ip, port, 30);
	if (handler == NULL) {
		fprintf(stderr, "udpserver_init error: %s\n", strerror(errno));
		ret = -2;
		goto end;
	}

	ret = dserver_set_handlers(handler, session_init, session_worker, session_exit);
	if (ret < 0) {
		fprintf(stderr, "udpserver_set_handler error[%d]: %s\n", ret, strerror(errno));
		ret = -3;
		goto end;
	}

	ret = dserver_udpserver_run(handler);
	if (ret < 0) {
		fprintf(stderr, "udpserver_run error[%d]: %s\n", ret, strerror(errno));
		ret = -4;
		goto end;
	}
 
end:
	dserver_log_exit();
	return ret;
}

static int session_init(void *arg)
{
	fprintf(stderr, "PROTOCOL(UDP): protocol_session_init.\n");

	if (arg == NULL) {
		fprintf(stderr, "protocol_session_init parameters error.\n");
		return -E_ARGS_ILLEGAL;
	}

	dserver_conn_t *conn = (dserver_conn_t *)arg;
	prot_node_t *prot = conn->c_prot_node;
	char client_ip[INET_ADDRSTRLEN] = {0};

	prot->p_data = strdup("def_udp:test data in default");

	ipv4_to_str(((struct sockaddr_in *)(&conn->c_csa))->sin_addr.s_addr, client_ip);
	fprintf(stderr, "session_init: load data: %s | client info: %s\n",
			(char *)prot->p_data, client_ip);

	return PROTOCOL_SUCCESS;
}

static prot_ret_t session_worker(void *arg)
{
	fprintf(stderr, "PROTOCOL(UDP): protocol_session_worker.\n");

	if (arg == NULL) {
		fprintf(stderr, "protocol_session_worker parameters error.\n");
		return PROTOCOL_ERROR;
	}

	dserver_conn_t *conn = (dserver_conn_t *)arg;
	prot_node_t *prot = conn->c_prot_node;

	if (conn->c_rsize == 0) {
		fprintf(stderr, "protocol_session_worker received data error.\n");
		return PROTOCOL_ERROR;
	}
	
	/* sendback data to socket directively */
	size_t global_data_len = strlen((char *)prot->p_data) + 1;
	conn->c_wsize = conn->c_rsize + global_data_len;
	snprintf(conn->c_wbuf, DSERVER_TX_BUFLEN, "%s:%s", (char *)prot->p_data, conn->c_rbuf);

	fprintf(stderr, "protocol_session_worker sending data[%s].\n", conn->c_wbuf);

	if (dserver_udp_data_sendout(prot) < 0) {
		fprintf(stderr, "protocol_session_worker sending data error.\n");
		return PROTOCOL_ERROR;
	}

	return PROTOCOL_SUCCESS;
//	return PROTOCOL_RESET;
//	return PROTOCOL_IGNORE;
//	return PROTOCOL_CLOSE;
}

static void session_exit(void *arg)
{
	fprintf(stderr, "PROTOCOL(UDP): protocol_session_exit.\n");

	if (arg == NULL) {
		fprintf(stderr, "protocol_session_init parameters error.\n");
		return;
	}

	dserver_conn_t *conn = (dserver_conn_t *)arg;
	prot_node_t *prot = conn->c_prot_node;
	char client_ip[INET_ADDRSTRLEN] = {0};

	ipv4_to_str(((struct sockaddr_in *)(&conn->c_csa))->sin_addr.s_addr, client_ip);
	fprintf(stderr, "session_exit: load data: %s | client info: %s\n",
			(char *)prot->p_data, client_ip);

	dfree(prot->p_data);

	return;
}
